package com.zhulong.saas.cloud.gateway.error;

import com.zhulong.common.basic.dto.Response;
import feign.FeignException;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.nio.file.AccessDeniedException;

import static org.springframework.web.reactive.function.server.RequestPredicates.all;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

/**
 * response错误处理
 */
public class ResponseErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

    public ResponseErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return route(all(), this::renderErrorResponse);
    }

    protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        Throwable throwable = getError(request);
        HttpStatus httpStatus = null;
        Response response = null;
        if (throwable instanceof InvalidTokenException) {
            httpStatus = HttpStatus.UNAUTHORIZED;
            response = Response.fail(GatewayBasicError.UNAUTHORIZED);
        } else if (throwable instanceof AccessDeniedException) {
            httpStatus = HttpStatus.FORBIDDEN;
            response = Response.fail(GatewayBasicError.FORBIDDEN);
        } else if (throwable instanceof NotFoundException) {
            httpStatus = HttpStatus.OK;
            response = Response.fail(GatewayBasicError.SERVER_UNVALIBLE);
        } else if (throwable instanceof FeignException) {
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            response = Response.fail(GatewayBasicError.SERVER_UNVALIBLE);
        }
        if (httpStatus != null) {
            return ServerResponse.status(httpStatus.value()).contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(response));
        }
        return super.renderErrorResponse(request);
    }


}
